package com.seanzx.common;

import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class NetSerializer {
    public static String serialize(NetRes netRes) {
        StringBuilder stringBuilder = new StringBuilder();

        stringBuilder.append(StringUtils.lpad(String.valueOf(netRes.executeTime), 6, '0'));
        stringBuilder.append(netRes.resultCode);
        stringBuilder.append(netRes.type);

        switch (netRes.type) {
            case TYPE_ROWS:
                stringBuilder.append(netRes.rows);
                break;
            case TYPE_DATA:
                for (List<String> row : netRes.results) {
                    for (String col : row) {
                        stringBuilder.append(col).append("\000");
                    }
                    stringBuilder.append('\001');
                }
                break;
            default:
                stringBuilder.append(netRes.resultMessage);
        }
        stringBuilder.append("\002\n");
        return stringBuilder.toString();
    }

    public static NetRes deserialize(String string) {
        NetRes netRes = new NetRes();
        netRes.executeTime = Integer.parseInt(string.substring(0, 6));
        netRes.resultCode = string.substring(6, 12);
        netRes.type = string.substring(12, 13).charAt(0);
        switch (netRes.type) {
            case TYPE_ROWS:
                netRes.rows = Integer.parseInt(string.substring(13));
                break;
            case TYPE_DATA:
                netRes.results = new ArrayList<>();

                String[] rows = string.substring(13).split("\001");
                for (String row : rows) {
                    String[] cols = row.split("\000");
                    List<String> columns = new ArrayList<>(Arrays.asList(cols));
                    netRes.results.add(columns);
                }
                netRes.rows = netRes.results.size();
                break;
            default:
                netRes.resultMessage = string.substring(13);
        }
        return netRes;
    }

    public static final char TYPE_DATA = '0';
    public static final char TYPE_ROWS = '1';
    public static final char TYPE_ERR = '2';
    public static final char TYPE_SUCCESS = '3';

    /**
     * 6 chars executeTime
     * 6 chars resultCode
     * 1 char type
     * resultCode is success, next chars are results
     * resultCode is failed, next chars are resultMessage
     * results 每列以/000 分隔， 每行以/001分隔
     */
    public static class NetRes {
        int executeTime;
        String resultCode;
        char type;
        String resultMessage;
        List<List<String>> results;
        int rows;

        public int getExecuteTime() {
            return executeTime;
        }

        public void setExecuteTime(int executeTime) {
            this.executeTime = executeTime;
        }

        public String getResultCode() {
            return resultCode;
        }

        public void setResultCode(String resultCode) {
            this.resultCode = resultCode;
        }

        public char getType() {
            return type;
        }

        public void setType(char type) {
            this.type = type;
        }

        public String getResultMessage() {
            return resultMessage;
        }

        public void setResultMessage(String resultMessage) {
            this.resultMessage = resultMessage;
        }

        public List<List<String>> getResults() {
            return results;
        }

        public void setResults(List<List<String>> results) {
            this.results = results;
        }

        public int getRows() {
            return rows;
        }

        public void setRows(int rows) {
            this.rows = rows;
        }
    }

    public static void main(String[] args) {
        NetRes netRes = new NetRes();
        netRes.executeTime = 2200;
        netRes.resultCode = "000000";
        netRes.type = TYPE_DATA;
        netRes.results = Lists.of(
                Lists.of("TABLE_NAME", "ROWS"),
                Lists.of("TABLE", "2"),
                Lists.of("COLUMN", "10"),
                Lists.of("TEST", "131")
        );
        NetRes deserialize = deserialize(serialize(netRes));
        assert deserialize.executeTime == 2200;
        assert deserialize.resultCode.equals("000000");
        System.out.println(deserialize.results);
    }
}
